package org.squabble.dao;

import java.io.Serializable;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.util.Assert;

public abstract class AbstractHibernateDAO<E> {

	private final Class<E> entityClass;
	private final SessionFactory sessionFactory;

	public AbstractHibernateDAO(Class<E> entityClass,
			SessionFactory sessionFactory) {

		Assert.notNull(entityClass, "entityClass must not be null");
		Assert.notNull(sessionFactory, "sessionFactory must not be null");

		this.entityClass = entityClass;
		this.sessionFactory = sessionFactory;
	}

	protected Criteria criteria() {
		return currentSession().createCriteria(entityClass);
	}

	protected Query query(String hql) {
		return currentSession().createQuery(hql);
	}

	protected Query queryByName(String queryName) {
		return currentSession().getNamedQuery(queryName);
	}
	
	protected Session currentSession() {
		return sessionFactory.getCurrentSession();
	}

	protected List<E> all() {
		return list(criteria());
	}

	public Class<E> getEntityClass() {
		return entityClass;
	}

	/* === BEGIN GENERICS SUPPRESSION WRAPPERS === */

	protected List<E> list(Criteria criteria) {
		return list(criteria, true);
	}

	@SuppressWarnings("unchecked")
	protected List<E> list(Criteria criteria, boolean cache) {
		criteria.setCacheable(cache);
		return criteria.list();
	}

	protected List<E> list(Query query) {
		return list(query, true);
	}

	@SuppressWarnings("unchecked")
	protected List<E> list(Query query, boolean cache) {
		query.setCacheable(cache);
		return query.list();
	}

	@SuppressWarnings("unchecked")
	protected E uniqueResult(Criteria criteria) {
		return (E) criteria.uniqueResult();
	}

	@SuppressWarnings("unchecked")
	protected E uniqueResult(Query query) {
		return (E) query.uniqueResult();
	}

	@SuppressWarnings("unchecked")
	protected E get(Serializable id) {
		return (E) currentSession().get(entityClass, id);
	}
	
	@SuppressWarnings("unchecked")
	protected E load(Serializable id) {
		return (E) currentSession().load(entityClass, id);
	}	
}